/*******************************************************************************
 * \brief   播放器、摄像机主程序，一直循环调用子模块
 * \details ui界面中调用此模块内的功能实现播放与录制
 *          使用纯C实现
 * \author  将狼才鲸
 * \date    2022-04-01
 * \note    中文编码：UTF-8，换行：Windows(CRLF)
 * \remarks 参考网址：
 *          [C语言多线程编程](https://www.cnblogs.com/zzdbullet/p/9526130.html)
 ******************************************************************************/

/************************************ 头文件 **********************************/
#include <stdio.h>      // printf fflush
#include <pthread.h>    // pthread_t pthread_create pthread_join
#include <unistd.h>     // sleep
#include "player.h"
#include "module.h"

/************************************ 宏定义 **********************************/
#define pr_info printf
#define EPERM 1 /* Operation not permitted */ // copy of errno.h

/*********************************** 全局变量 *********************************/
int pstate = PSTATE_NONE; // 状态机
static struct module * main_module = NULL;
static struct module * second_main_module = NULL;
static void player_run(void);
extern struct module g_module_pcmin;
extern struct module g_module_audioenc;
extern struct module g_module_yuvin;
extern struct module g_module_videocenc;
extern struct module g_module_mp4mux;
extern struct module g_module_filesave;

/*********************************** 接口函数 *********************************/
/**
 * \brief 初始化，创建一个一直执行的主线程
 */
int player_init(int type)
{
    int ret;
    pthread_t thrd;

    // 创建并运行线程
    ret = pthread_create(&thrd, NULL, (void *)player_run, NULL);

    pr_info("player thread run pass\n");
    fflush(stdout); // 不及时刷新的话Qt应用程序输出中没有数据

    // 启动录音
    if (type == TYPE_AUDIO) {
        // AAC直接保存为文件
        main_module = &g_module_pcmin;
        main_module->settarget(&g_module_audioenc);
        g_module_audioenc.settarget(&g_module_filesave);

        // PCM直接保存为文件
        //main_module = &g_module_pcmin;
        //main_module->settarget(&g_module_filesave);
    }
    // 启动录像
    if (type == TYPE_VIDEO) {
        // 视频加到MP4等容器中保存为文件
        main_module = &g_module_yuvin;
        main_module->settarget(&g_module_videocenc);
        g_module_videocenc.settarget(&g_module_mp4mux);

        // 音频加到MP4等容器中保存为文件
        second_main_module = &g_module_pcmin;
        second_main_module->settarget(&g_module_audioenc);
        g_module_audioenc.settarget(&g_module_mp4mux);
    }

    pstate = PSTATE_INITED;

    return ret;
}

int player_start(void)
{
    if (pstate != PSTATE_INITED && pstate != PSTATE_STOPED)
        return -EPERM;

    pr_info("Start record...\n");

    pstate = PSTATE_STARTED;
    pstate = PSTATE_RUNNING_IDLE;

    return 0;
}

int player_pause(void)
{
    return 0;
}

int player_resume(void)
{
    return 0;
}

int player_stop(void)
{
    if (pstate < PSTATE_STARTED || pstate >= PSTATE_STOPED)
        return -EPERM;

    pr_info("Stop record\n");

    return 0;
}

int player_exit(void)
{
    return 0;
}

/*********************************** 私有函数 *********************************/
/**
 * \brief 播放器/录像机主模块，一直循环执行
 */
static void player_run(void)
{
    while (pstate < PSTATE_STARTED) {
        // wait started
    }

    pr_info("main module: %s\n", main_module->name);
    fflush(stdout);
    main_module->init();
    if (second_main_module)
        second_main_module->init();

    main_module->start(NULL);
    if (second_main_module)
        second_main_module->start(NULL);

    while (pstate < PSTATE_STOPED) {
        /* 运行主模块 */
        main_module->run();
        if (second_main_module)
            second_main_module->run();
    }

    main_module->stop();
    if (second_main_module)
        second_main_module->stop();

    main_module->exit();
    if (second_main_module)
        second_main_module->exit();

    pr_info("main module %s exit\n", main_module->name);
    fflush(stdout);
}

/******** 文件结尾 ********/
